//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
using System;

using System.Security.Permissions;
using System.Security.Principal;

using System.ServiceModel;
using System.ServiceModel.Activation;

using System.Threading;

using System.Web.Security;

using System.Data.SqlClient;
using System.Configuration;
using System.Data;
using System.Collections.Generic;

namespace Microsoft.ServiceModel.Samples
{
    // Define a service contract.
    [ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
    public interface ICalculatorMethods
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
        [OperationContract]
        double Multiply(double n1, double n2);
        [OperationContract]
        double Divide(double n1, double n2);
    }

    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface IDataBaseMethods
    {
        [OperationContract]
        string DataBaseSelect(string cmdString);
    }

    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface IAspNetUsersRolesMethods
    {
        [OperationContract]
        string AddUser(string user, string password, string email);
        [OperationContract]
        bool RemoveUser(string user);
        [OperationContract]
        bool AddUserToRole(string user, string role);
        [OperationContract]
        string[] GetUserRoles(string user);
        [OperationContract]
        string[] GetAllUsers();
        [OperationContract]
        string[] GetAllRoles();
        [OperationContract]
        string[] GetAllUserRoles(string user);
    }

    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface ICalculator: IAspNetUsersRolesMethods,IDataBaseMethods,ICalculatorMethods
    {
 
    }
    //PrivateSession create an instance per channel session
    //This requires a binding that supports session
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    // Service class which implements the service contract.
    public class CalculatorService : ICalculator
    {
        #region ICalculatorMethods Members
        // Allows all Users to call the Add method
        //[PrincipalPermission(SecurityAction.Demand, Role = "Users")]
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            return result;
        }

        // Allows all Users to call the Subtract method
        //[PrincipalPermission(SecurityAction.Demand, Role = "Users")]
        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            return result;
        }

        // Only allow Registered Users to call the Multiply method
        //[PrincipalPermission(SecurityAction.Demand, Role = "Registered Users")]
        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            return result;
        }

        // Only allow Super Users to call the Divide method
        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            return result;
        }
 
        #endregion

        #region IAspNetUsersRoles Members

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public string AddUser(string user, string password, string email)
        {
            MembershipCreateStatus status;
            Membership.CreateUser(user, password, email, "My dog name?", "Flufly", true,out status);
            return status.ToString();
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public bool RemoveUser(string user)
        {
            return Membership.DeleteUser(user);
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public bool AddUserToRole(string user, string role)
        {
            string[] users = new string[1];
            users[0]=user;
            Roles.AddUsersToRole(users, role);
            return Roles.IsUserInRole(user, role);
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public string[] GetUserRoles(string user)
        {
            return Roles.GetRolesForUser(user);
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public string[] GetAllUsers()
        {
            MembershipUserCollection users =  Membership.GetAllUsers();
            string[] userTab = new string[users.Count];
            int i=0;
            foreach (MembershipUser usr in users)
            {
                userTab[i] = usr.UserName;
                i++;
            }
            return userTab;
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public string[] GetAllRoles()
        {
            return Roles.GetAllRoles();
        }

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public string[] GetAllUserRoles(string usr)
        {
            return Roles.GetRolesForUser(usr);
        }
        #endregion

        #region IDataBaseMethods Members

        //[PrincipalPermission(SecurityAction.Demand, Role = "Super Users")]
        public string DataBaseSelect(string cmdString)
        {
            try
            {
                string connStr = ConfigurationManager.ConnectionStrings["Maklaren"].ConnectionString;
                SqlDataAdapter adapter = new SqlDataAdapter(cmdString, connStr);
                DataTable dt = new DataTable("table");
                adapter.Fill(dt);

                string returnString = "";

                foreach (DataRow dr in dt.Rows)
                {
                    foreach (DataColumn dc in dt.Columns)
                    {
                        returnString += dr[dc].ToString() + " ; ";
                    }
                    returnString += "\n";
                }
                return returnString;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

        }

        #endregion
    }

    public class CalculatorServiceHostFactory : ServiceHostFactoryBase
    {
        public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            return new CalculatorServiceHost(baseAddresses);
        }
    }

    class CalculatorServiceHost : ServiceHost
    {
        #region CalculatorServiceHost Constructor
        /// <summary>
        /// Constructs a CalculatorServiceHost. Calls into SetupUsersAndroles to 
        /// set up the user and roles that the CalculatorService allows
        /// </summary>
        public CalculatorServiceHost(params Uri[] addresses)
            : base(typeof(CalculatorService), addresses)
        {
            FirstRun();
        }
        #endregion

        internal static void FirstRun()
        {
            try
            {
                if (Membership.GetUser("admin") != null)
                    Membership.DeleteUser("admin");
                if (Membership.GetUser("register") != null)
                    Membership.DeleteUser("register");

                Membership.CreateUser("admin", "adminpass1-", "admin@admin");
                Membership.CreateUser("register", "register", "register");

                if (!Roles.RoleExists("Users"))
                    Roles.CreateRole("Users");
                if (!Roles.RoleExists("Super Users"))
                    Roles.CreateRole("Super Users");
                if (!Roles.RoleExists("register user"))
                    Roles.CreateRole("register user");
                string[] r = new string[1];
                r[0] = "admin";
                if (!Roles.IsUserInRole("admin", "Super Users"))
                    Roles.AddUsersToRole(r, "Super Users");
                r[0] = "register";
                if (!Roles.IsUserInRole("register user", "register user"))
                    Roles.AddUsersToRole(r, "register user");

            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// Sets up the user and roles that the CalculatorService allows
        /// </summary>
        /// 
        internal static void SetupUsersAndRoles()
        {
            // Create some arrays for membership and role data
            string[] users = { "Alice", "Bob", "Charlie" };
            string[] emails = { "alice@example.org", "bob@example.org", "charlie@example.org" };
            string[] passwords = { "ecilA-123", "treboR-456", "eilrahC-789" };
            string[] roles = { "Super Users", "Registered Users", "Users" };
            
            // Clear out existing user information and add fresh user information
            for (int i = 0; i < emails.Length; i++)
            {
                if (Membership.GetUserNameByEmail(emails[i]) != null)
                    Membership.DeleteUser(users[i], true);

                Membership.CreateUser(users[i], passwords[i], emails[i]);
            }

            // Clear out existing role information and add fresh role information
            // This puts Alice, Bob and Charlie in the Users Role, Alice and Bob 
            // in the Registered Users Role and just Alice in the Super Users Role.
            for (int i = 0; i < roles.Length; i++)
            {
                if (Roles.RoleExists(roles[i]))
                {
                    foreach (string u in Roles.GetUsersInRole(roles[i]))
                        Roles.RemoveUserFromRole(u, roles[i]);

                    Roles.DeleteRole(roles[i]);
                }

                Roles.CreateRole(roles[i]);

                string[] userstoadd = new string[i + 1];

                for (int j = 0; j < userstoadd.Length; j++)
                    userstoadd[j] = users[j];

                Roles.AddUsersToRole(userstoadd, roles[i]);
            }
        }
    }
}
